﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;


namespace FingerTip.Infrastructure.HttpClient
{
    public class HttpRequestor
    {
        private readonly Api _root;
        private readonly MethodType _method;
        private object _data;
        private IDictionary<string, string> _headers;

        public HttpRequestor(Api root, MethodType method)
        {
            _root = root;
            _method = method;
        }

        public HttpRequestor With(object data)
        {
            _data = data;
            return this;
        }

        public HttpRequestor SetHeaders(IDictionary<string, string> headers)
        {
            _headers = headers;
            return this;
        }

        public T To<T>(string tailUrl)
        {
            var result = default(T);

            void Parser(string json)
            {
                result = JsonConvert.DeserializeObject<T>(json);
            }

            Stream(tailUrl, Parser);
            return result;
        }

        public void Stream(string tailUrl, Action<string> parser)
        {
            var request = SetupConnection(_root.GetUrl(tailUrl));

            if (HasOutput())
            {
                SubmitData(request);
            }
            else if (_method == MethodType.Put)
            {
                _headers.Add(new KeyValuePair<string, string>("Content-Length", "0"));
            }

            using (var response = request.GetResponse())
            {
                using (var stream = response.GetResponseStream())
                {
                    var data = new StreamReader(stream ?? throw new InvalidOperationException()).ReadToEnd();
                        
                    parser(data);
                }
            }
        }

        private bool HasOutput()
        {
            return _method == MethodType.Post || _method == MethodType.Put && _data != null;
        }

        private void SubmitData(WebRequest request)
        {
            request.ContentType = "application/json";
            using (var writer = new StreamWriter(request.GetRequestStreamAsync().Result))
            {
                var data = JsonConvert.SerializeObject(_data);
                writer.Write(data);
                writer.Flush();
            }
        }

        private WebRequest SetupConnection(Uri url)
        {
            return SetupConnection(url, _method);
        }

        private  WebRequest SetupConnection(Uri url, MethodType methodType)
        {
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = methodType.ToString().ToUpperInvariant();
            request.Headers["Accept-Encoding"] = "gzip";
            if (_headers != null && _headers.Count > 0)
            {
                foreach (var header in _headers)
                {
                    request.Headers[header.Key] = header.Value;
                }
            }
            request.ContinueTimeout = 60000;
            return request;
        }
    }
}
